package com.atguigu.gmall.wms.listener;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.wms.entity.WareSkuEntity;
import com.atguigu.gmall.wms.mapper.WareSkuMapper;
import com.atguigu.gmall.wms.service.WareSkuService;
import com.atguigu.gmall.wms.vo.StockLockedVo;
import com.rabbitmq.client.Channel;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.io.IOException;
import java.util.List;
import java.util.Map;


@Configuration
public class WareSkuListener {
    @Autowired  //StringRedisTemplate和RedisTemplate不能混用
    StringRedisTemplate redisTemplate;
    @Autowired
    WareSkuMapper wareSkuMapper;
    @Autowired
    WareSkuService wareSkuService;
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(
                    name = "pay.stock.queue"
            ),
            exchange = @Exchange(
                    name = "pay.exchange",
                    type = ExchangeTypes.TOPIC,
                    ignoreDeclarationExceptions = "true"
            ),
            key = "pay.success"
    ))
    public void updateStockAndSales(Message message , String orderToken , Channel channel) throws IOException {
        try {
            //根据orderToken获取它锁定的 库存集合
            String jsonStr = redisTemplate.opsForValue().get("lock:stock:" + orderToken);
            if(StringUtils.isNotBlank(jsonStr)){
                //有锁定的库存数据
                List<StockLockedVo> stockLockedVos = JSON.parseArray(jsonStr, StockLockedVo.class);
                //遍历每一个库存：加销量 减锁定的库存  减库存
                stockLockedVos.forEach(stockLockedVo -> {
                    WareSkuEntity wareSkuEntity = wareSkuService.getById(stockLockedVo.getWareSkuId());
                    wareSkuEntity.setStock(wareSkuEntity.getStock() - stockLockedVo.getCount());
                    wareSkuEntity.setStockLocked(wareSkuEntity.getStockLocked() - stockLockedVo.getCount());
                    wareSkuEntity.setSales(wareSkuEntity.getSales()+stockLockedVo.getCount());
                    wareSkuService.updateById(wareSkuEntity);

                });
                redisTemplate.delete("lock:stock:" + orderToken);
            }
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),
                    false);
        } catch (Exception e) {
            e.printStackTrace();
            if(message.getMessageProperties().isRedelivered()){
                //丢弃消息： 可以给队列绑定死信队列
                channel.basicReject(message.getMessageProperties().getDeliveryTag(),
                        false);
            }else{
                //第一次消费失败
                channel.basicNack(message.getMessageProperties().getDeliveryTag(),
                        false,true);
            }
        }
    }



    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(
                    name = "stock.queue"
            ),
            exchange = @Exchange(
                    name = "order.exchange",
                    type = ExchangeTypes.TOPIC,
                    ignoreDeclarationExceptions = "true"
            ),
            key = "stock.unlock"
    ))
    public void unlockStock(Message message , String token , Channel channel) throws IOException {
        try {
            //token代表需要释放库存的订单token
            String jsonStr = redisTemplate.opsForValue().get("lock:stock:" + token);
            if(!StringUtils.isEmpty(jsonStr)){
                List<StockLockedVo> stockLockedVos = JSON.parseArray(jsonStr, StockLockedVo.class);
                //遍历释放库存
                stockLockedVos.forEach(stockLockedVo -> {
                    wareSkuMapper.unlockStock(stockLockedVo.getWareSkuId() ,
                            stockLockedVo.getCount());
                });
              //遍历删除完成：删除锁定库存的缓存
                redisTemplate.delete("lock:stock:" + token);
            }
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),
                    false);
        } catch (Exception e) {
            e.printStackTrace();
            if(message.getMessageProperties().isRedelivered()){
                //丢弃消息： 可以给队列绑定死信队列
                channel.basicReject(message.getMessageProperties().getDeliveryTag(),
                        false);
            }else{
                //第一次消费失败
                channel.basicNack(message.getMessageProperties().getDeliveryTag(),
                        false,true);
            }
        }
    }
}
